﻿using libC.semantic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace libC.translate
{
    /// <summary>
    /// C# 类型声明
    /// </summary>
    internal class CSTypeDecl
    {
        /// <summary>
        /// 是否有 引用
        /// </summary>
        public bool hasRef;
        /// <summary>
        /// 是否有指针
        /// </summary>
        public bool hasPoint;
        /// <summary>
        /// 数组的维度数
        /// </summary>
        public int arrCount;
        /// <summary>
        /// C#类型字符串
        /// </summary>
        public string typeWord;
        /// <summary>
        /// 是空结构体类型
        /// </summary>
        public bool isVoidStruct;
        /// <summary>
        /// 是含指针用作 数组的有效别名
        /// </summary>
        public bool isTAliasTagArr;
        /// <summary>
        /// 类型别名 源类型单词
        /// </summary>
        public string typeAliasSrcWord;
        /// <summary>
        /// 是 char16_t 类型
        /// </summary>
        public bool isChar16;
        /// <summary>
        /// 是 结构体
        /// </summary>
        public bool isStruct;
        /// <summary>
        /// 是枚举
        /// </summary>
        public bool isEnum;
    }

    /// <summary>
    /// C# 语言 wrap code 生成器
    /// </summary>
    internal class generatorCSharp : IWrapGenerator, IDisposable
    {
        delegate string retStringPDel(string _t, string _n);
        delegate string retStringPDefDel(string _t, string _n, List<string> defVal);

        /// <summary>
        /// 参数名 后缀类型
        /// </summary>
        enum PNameSuffix
        {
            /// <summary>
            /// 空
            /// </summary>
            NONE,
            /// <summary>
            /// 作为 返回
            /// </summary>
            OUT,
            /// <summary>
            /// 作为数组
            /// </summary>
            ARRAY,
            /// <summary>
            /// 作为 句柄
            /// </summary>
            HANDLE
        }

        /*
         * C# wrap 要处理的情况列表：
         * 1.基础类型映射
         * 
         * 2.C 函数指针 转 C#委托 
         *  无return 无参数 直接用 Action
         *  
         * 3.字符串参数
         *  char16_t * 直接 看成 string（DllImport 要设置 CharSet = CharSet.Unicode ）
         *  
         * 3.指针消歧义（）
         *  约定 char16_t * C# 当 string
         *  空定义的结构 类型指针，作为handle
         *  形参指针 作为 传出, 命名后缀_out 当做引用ref
         *  形参指针 作为 传入, 命名后缀_handle 当做句柄处理
         *  形参指针 作为 传入, 命名后缀_arr 当做数组处理
         *  
         *  返回值类型指针 为返回值不明确，报错提示。 例如： int* func();
         *  用别名来标注意图 例如：typedef int* int_Array;  int_Array func();
         *  返回值指针 作为 数组 ,命名 类型_Array;
         *  基类型列表：sbyte,byte,short,ushort,int,uint,long,ulong,float,double,枚举，结构体
         *  返回值指针 作为 handle ,直接使用 void*;
         *  
         * 4.空定义结构
         * 约定 空定义结构 作为 handle ，结构体中 只放一个 uint64 来保存内存地址（抛弃 32位）
         * 
         * 5.安全包装
         * unsafe 的函数都不能 public ，要包用重载包一层，也就是替换所有的 指针实现
         *  返回值指针
         *  参数指针
         *  指针函数 的 返回值和参数指针
         */

        public string nameSpace;
        public string className;
        public string dllFile;
        public bool forceSafe;

        private semanticAnalyzer _semAnaly;
        private string _code;
        private const string STR = "string";
        private const string VD = "void";
        private const string NL = "null";
        private const string NLP = "nullprt";
        private const string BL = "bool";
        private const string FAL = "false";
        private const string TRU = "true";

        private const string PUB = "public";
        private const string STC = "static";
        private const string STU = "struct";
        private const string CLA = "class";
        private const string USF = "unsafe";
        private const string DLG = "delegate";
        private const string ETR = "extern";
        private const string C16 = "char16_t";
        private const string C16P = "char16_t*";
        private const string SAF = "safe";
        private const string RET = "return";
        private const string HDL = "handle";
        public const string RKEY = "__retVal__";

        private static readonly Dictionary<string, string> CBaseTypeRemap = new Dictionary<string, string>()
        {
            ["char"] = "byte",

            ["unsigned char"] = "byte",
            ["unsigned short"] = "ushort",
            ["unsigned int"] = "uint",
            ["unsigned long"] = "ulong",

            ["signed char"] = "sbyte",
            ["signed short"] = "short",
            ["signed int"] = "int",
            ["signed long"] = "long",

            ["int8_t"] = "sbyte",
            ["int16_t"] = "short",
            ["int32_t"] = "int",
            ["int64_t"] = "long",
            ["uint8_t"] = "byte",
            ["uint16_t"] = "ushort",
            ["uint32_t"] = "uint",
            ["uint64_t"] = "ulong",

            ["int_least8_t"] = "sbyte",
            ["int_least16_t"] = "short",
            ["int_least32_t"] = "int",
            ["int_least64_t"] = "long",
            ["uint_least8_t"] = "byte",
            ["uint_least16_t"] = "ushort",
            ["uint_least32_t"] = "uint",
            ["uint_least64_t"] = "ulong",

            ["int_fast8_t"] = "sbyte",
            ["int_fast16_t"] = "short",
            ["int_fast32_t"] = "int",
            ["int_fast64_t"] = "long",
            ["uint_fast8_t"] = "byte",
            ["uint_fast16_t"] = "ushort",
            ["uint_fast32_t"] = "uint",
            ["uint_fast64_t"] = "ulong",

            ["char16_t"] = "char",  //用作string 
        };
        private static readonly List<string> usingList = new List<string>() {
            "System",
            "System.Runtime.InteropServices"
        };
        private int indentLevel;
        private Dictionary<string, bool> _voiddeleFunDic;
        private Dictionary<string, functionInfo> _unsafeDeleFunDic;
        private Dictionary<string, functionInfo> _allDeleFunDic;
        private Dictionary<string, bool> _voidStructDic;
        private Dictionary<string, CSTypeDecl> _funCsTypeDeclDic;
        private Dictionary<string, typeAliasInfo> _typeAliasDic;
        private Dictionary<string, PNameSuffix> _pNameSuffixDic;
        private Dictionary<string, enumInfo> _enumDic;
        private Dictionary<string, structInfo> _structDic;

        private string indentSP => transTool.indentSp(indentLevel);
        private void init()
        {
            _code = "";
            _semAnaly = null;
            indentLevel = 0;
            _voiddeleFunDic = new Dictionary<string, bool>();
            _unsafeDeleFunDic = new Dictionary<string, functionInfo>();
            _allDeleFunDic = new Dictionary<string, functionInfo>();
            _voidStructDic = new Dictionary<string, bool>();
            _typeAliasDic = new Dictionary<string, typeAliasInfo>();
            _funCsTypeDeclDic = new Dictionary<string, CSTypeDecl>();
            _pNameSuffixDic = new Dictionary<string, PNameSuffix>();
            _enumDic = new Dictionary<string, enumInfo>();
            _structDic = new Dictionary<string, structInfo>();
        }
        /// <summary>
        /// 获取 生成的wrap code
        /// </summary>
        /// <returns></returns>
        public string getWrapCode()
        {
            return _code;
        }
        public void parse(semanticAnalyzer semAnaly)
        {
            //初始化状态
            init();
            //
            _semAnaly = semAnaly;

            //遍历树 ， 筛选 有 （extern "C"）导出标记的函数
            var funIdsDic = new Dictionary<uint, List<uint>>();
            //分析 返回值 、参数定义 ， 收集相关 用户自定义类型
            var cTypeDic = new Dictionary<uint, List<uint>>();
            transTool.limitFun(_semAnaly, funIdsDic, cTypeDic);
            //头信息
            transTool.addHaedInfomation(ref _code);
            //头部 using
            addStrUsings(usingList);
            //写文本
            if (!string.IsNullOrEmpty(nameSpace))
            {
                addStrNameSpace(nameSpace);     //增加class 字符串
            }
            addStrClass(className);                //增加class 字符串
            addStrDllfile(dllFile);             //

            //handle_void 的声明
            addHandleDecl(VD);
            //写 枚举、结构体
            insertCTypesDic(cTypeDic);

            //写 函数 ,语言基础类型 映射
            insertFunsDic(funIdsDic);

            //class 结尾
            addStrBlockEnd();
            //nameSpace
            if (!string.IsNullOrEmpty(nameSpace))
            {
                addStrBlockEnd();
            }
        }
        /// <summary>
        /// 释放销毁
        /// </summary>
        public void Dispose()
        {
            if (_voiddeleFunDic != null) _voiddeleFunDic.Clear();
            if (_unsafeDeleFunDic != null) _unsafeDeleFunDic.Clear();
            if (_allDeleFunDic != null) _allDeleFunDic.Clear();
            if (_voidStructDic != null) _voidStructDic.Clear();
            if (_typeAliasDic != null) _typeAliasDic.Clear();
            if (_funCsTypeDeclDic != null) _funCsTypeDeclDic.Clear();
            if (_pNameSuffixDic != null) _pNameSuffixDic.Clear();
            if (_enumDic != null) _enumDic.Clear();
            if (_structDic != null) _structDic.Clear();
            _semAnaly = null;
            _voiddeleFunDic = null;
            _unsafeDeleFunDic = null;
            _allDeleFunDic = null;
            _voidStructDic = null;
            _typeAliasDic = null;
            _funCsTypeDeclDic = null;
            _pNameSuffixDic = null;
            _enumDic = null;
            _structDic = null;
        }

        
        //添加 块 } 结尾
        private void addStrBlockEnd()
        {
            indentLevel--;
            _code += $"{indentSP}}}{transTool.LF}";
        }
        //添加 命名空间 字符串
        private void addStrNameSpace(string ns)
        {
            _code += $"{transTool.NSP} {ns} {"{"}{transTool.LF}";
            indentLevel++;
        }
        //添加 类名 字符串
        private void addStrClass(string cName)
        {
            _code += $"{indentSP}{PUB} {CLA} {cName} {"{"}{transTool.LF}";
            indentLevel++;
        }
        //添加 dll文件 字符串定义
        private void addStrDllfile(string dllFile)
        {
            _code += $"{indentSP}private const string dllFile = @\"{dllFile}\";{transTool.LF}";
        }

        //添加 函数 dllImp 标记
        private void addStrDLLImp(bool needCCon, bool needCharSet)
        {
            string CallingConvention = !needCCon ? "" : $", CallingConvention = CallingConvention.Cdecl";
            //needCharSet = false;// CharSet = CharSet.Unicode , 存在问题 暂时 屏蔽
            string CharSet = !needCharSet ? "" : ", CharSet = CharSet.Unicode";
            _code += $"{indentSP}[DllImport(dllFile {CallingConvention}{CharSet})]{transTool.LF}";
        }
        //添加 using 标记
        private void addStrUsings(List<string> list)
        {
            foreach (var item in list)
            {
                _code += $"using {item};{transTool.LF}";
            }
        }
        //添加 句柄声明
        private void addHandleDecl(string hName)
        {
            //按 约定空结构 作为 handle ，植入一个 uint64 指向对象的地址
            _code += $"{indentSP}{PUB} {STU} {HDL}_{hName} {{ {PUB} UInt64 ptr; }}{transTool.LF}";
        }

        //插入 自定义类型 通过 字典
        private void insertCTypesDic(Dictionary<uint, List<uint>> cTypeDic)
        {
            _code += $"//自定义类型 {transTool.LF}";
            foreach (var item in cTypeDic)
            {
                uint astTd = item.Key;
                var cTypes = item.Value;
                var semAst = _semAnaly.getSemantAst(astTd);
                for (int i = 0, len = cTypes.Count; i < len; i++)
                {
                    insertCType(semAst, cTypes[i]);
                }
            }
        }
        //插入 自定义 类型字符
        private void insertCType(semanticAST semAst, uint _nodeId)
        {
            var _info = semAst.getSemantInfo(_nodeId);
            if (_info == null) return;
            switch (_info.getType())
            {
                //case SemanticInfoType.EXPR:
                //    break;
                //case SemanticInfoType.Field:
                //break;
                case SemanticInfoType.ENUM:
                    insertEnum((enumInfo)_info);
                    break;
                case SemanticInfoType.TYPE_ALIAS:
                    _typeAliasDic[_info.name] = (typeAliasInfo)_info;
                    break;
                case SemanticInfoType.STRUCT:
                    var stcInfo = (structInfo)_info;
                    if (stcInfo.decls.Count > 0)
                    {
                        insertStruct(semAst, _nodeId);
                    }
                    else
                    {
                        insertVoidStruct(stcInfo);
                    }
                    break;
                case SemanticInfoType.FUNCTION:
                    insertDeleFun((functionInfo)_info);
                    break;
            }
        }
        //插入 委托函数定义
        private void insertDeleFun(functionInfo funInfo)
        {
            if (funInfo.isVoidFun)
            {
                //是 voidFun  不写入
                _voiddeleFunDic[funInfo.name] = true;
                return;
            }

            bool isLowLimit = false;
            _allDeleFunDic[funInfo.name] = funInfo;
            if (!string.IsNullOrEmpty(funInfo.exception))
            {
                if (forceSafe)
                {
                    //函数有异常信息 
                    _code += $"{indentSP} {DLG} {VD} {funInfo.name}( ); /*{funInfo.exception}*/{transTool.LF}";
                    return;
                }
                else
                {
                    isLowLimit = true;
                    //insertDeleFunLow(funInfo);
                }
            }

            //委托是否安全
            bool isSafe = !isDeleFunUnsafe(funInfo);
            //返回 类型
            var retTDecl = getcsTypeDecl(funInfo.ret_type);
            string realRetType = typeStrRet(retTDecl);

            //参数
            string argsStr = getDeleFunArgsStr(funInfo, false, true);

            //获取参数字符串
            string pubStr = isSafe || isLowLimit ? PUB + " " : "";       //public 标记
            string usfStr = isSafe ? "" : USF + " ";    //是否需要 unsafe 标记

            //函数声明
            _code += $"{indentSP}{pubStr}{usfStr}{DLG} {realRetType} {funInfo.name}({argsStr});{transTool.LF}";

            //是否是一个 安全的
            if (!isSafe)
            {
                _unsafeDeleFunDic[funInfo.name] = funInfo;     //存入字典
            }
            //有指指针的情况，需要 再做一次安全隔离
            if (isLowLimit || isSafe) return;
            realRetType = typeStrRet(retTDecl);
            string safe_argsStr = getDeleFunArgsStr(funInfo, true);
            //声明一个 安全的委托 
            _code += $"{indentSP}{PUB} {DLG} {realRetType} {funInfo.name}_{SAF}({safe_argsStr});{transTool.LF}";
        }
        //文本中 插入 自定义枚举
        private void insertEnum(enumInfo info)
        {
            //存入字典
            _enumDic[getFillName(info)] = info;

            //枚举名
            _code += $"{indentSP}{PUB} enum {info.name}";
            //枚举体开始
            _code += "{" + transTool.LF;
            indentLevel++;
            var decls = info.enums_decl;
            for (int i = 0, len = decls.Count; i < len; i += 2)
            {
                var declName = decls[i];
                var declval = decls[i + 1];
                _code += $"{indentSP}{declName} ";

                if (!string.IsNullOrEmpty(declval))
                {
                    //val 是字面 常量
                    _code += $"= {declval}";

                    //val 是表达式
                }
                _code += $",{transTool.LF}";
            }

            //枚举结尾
            addStrBlockEnd();
        }
        //插入结构体
        private void insertStruct(semanticAST semAst, uint nodeID)
        {

            var info = (structInfo)semAst.getSemantInfo(nodeID);
            //存入字典
            _structDic[getFillName(info)] = info;
            var node = semAst.getNode(nodeID);
            //结构名
            _code += $"{indentSP}{PUB} struct {info.name}";
            //结构体开始
            _code += "{" + transTool.LF;
            indentLevel++;//缩进++

            //递归 子类型定义
            var cs = node.children;
            if (cs != null && cs.Count > 0)
            {
                for (int i = 0, len = cs.Count; i < len; i++)
                {
                    insertCType(semAst, cs[i].id);
                }
            }

            //遍历结构体定义
            var decls = info.decls;
            for (int i = 0, len = decls.Count; i < len; i += 2)
            {
                var _t = decls[i];
                var _name = decls[i + 1];
                //转换类型
                //_t = arrTypeStrConver(_t);
                //_t = typeStrConver(_t);
                var t_decl = getcsTypeDecl(_t);
                _t = typeStr(t_decl, true);
                _code += $"{indentSP}{PUB} {_t} {_name};{transTool.LF}";
            }

            //结构结尾
            addStrBlockEnd();
        }
        //插入 空结构体
        private void insertVoidStruct(structInfo info)
        {
            _voidStructDic[info.name] = true;
            addHandleDecl(info.name);
        }
        private void insertFunsDic(Dictionary<uint, List<uint>> funIdsDic)
        {
            _code += $"//函数 {transTool.LF}";

            foreach (var item in funIdsDic)
            {
                uint id = item.Key;
                var funs = item.Value;
                insertFuns(id, funs);
            }
        }

        //插入 函数
        private void insertFuns(uint astID, List<uint> funs)
        {
            //单个文件
            var semAst = _semAnaly.getSemantAst(astID);
            var node = semAst.node;
            for (int i = 0, len = funs.Count; i < len; i++)
            {
                var funInfo = (functionInfo)semAst.getSemantInfo(funs[i]);

                bool isLowLimit = false;
                //函数是否有异常？
                string excp = transTool.getFunExcep(funInfo, _allDeleFunDic);
                if (!string.IsNullOrEmpty(excp))
                {
                    if (forceSafe)
                    {
                        //生成异常提示 空函数
                        _code += $"{indentSP}{PUB} {STC} void {funInfo.name}(params object[] objs){{{transTool.LF}";
                        indentLevel++;
                        _code += $"{indentSP}Console.WriteLine(@\"{excp}\");{transTool.LF}";
                        addStrBlockEnd();
                        //Console.WriteLine(excp);
                        continue;
                    }
                    else
                    {
                        isLowLimit = true;
                        //insertFunLow(funInfo);
                    }
                }

                bool hasPC16 = false;
                //检查一遍 返回值类型
                //返回值类型
                var retTDecl = getcsTypeDecl(funInfo.ret_type);
                string realRetType = typeStrRet(retTDecl, true);     //这里char16_t* 不要转 string了
                bool hasRetC16 = retTDecl.hasPoint && retTDecl.isChar16;
                //检查 函数 是否安全
                bool isSafe = !isFunUnsafe(funInfo);
                //参数
                //获取参数字符串
                string argsStr = getFunArgsStr(funInfo, false, ref hasPC16);
                string pubStr = isSafe || isLowLimit ? PUB + " " : "";
                string usfStr = isSafe ? "" : USF + " ";    //是否需要 unsafe 标记
                //判断是否需要生成一个安全的 函数

                //dllImport 
                bool needCC = true;
                bool needCharSet = hasPC16 || hasRetC16;   //char16_t 当成 string 使用时，需要
                //引入DLL C# 特性
                addStrDLLImp(needCC, needCharSet);
                //函数声明
                _code += $"{indentSP}{pubStr}{usfStr}{STC} {ETR} {realRetType} {funInfo.name}({argsStr});{transTool.LF}";

                if (isLowLimit || isSafe) continue;
                //重载的形式 定义实现 安全函数
                realRetType = typeStrRet(retTDecl);

                bool _Nc16 = false;
                string s_argsStr = getFunArgsStr(funInfo, true, ref _Nc16);

                //前半段
                _code += $"{indentSP}{PUB} {STC} {realRetType} {funInfo.name}_{SAF}({s_argsStr}){{{transTool.LF}";
                indentLevel++;
                //中段定义部分
                //unsafe set
                _code += $"{indentSP}{USF} {{ {transTool.LF}";
                indentLevel++;
                string fixedStr = "";
                string callStr = "";
                string deleFunStr = "";
                var fixedDic = new Dictionary<string, string>();
                //遍历参数，收集 safe函数体信息
                for (int j = 0, len1 = funInfo.args.Count; j < len1; j += 2)
                {
                    if (j > 1)
                    {
                        callStr += " ,";
                    }
                    var _t = funInfo.args[j];
                    var _n = funInfo.args[j + 1];
                    var _callN = _n;
                    var t_decl = getcsTypeDecl(_t);
                    var pNSuffix = getPNameSuffix(_n);
                    //指针类型
                    if (isRealPointParam(t_decl, _n))
                    {
                        string fixedT = t_decl.typeWord;
                        if (!fixedDic.ContainsKey(fixedT))
                        {
                            fixedDic[fixedT] = "";
                        }

                        if (fixedDic[fixedT] != "") fixedDic[fixedT] += " ,";
                        var __n = "_" + _n;
                        var refStr = pNSuffix == PNameSuffix.OUT ? "&" : "";
                        //拼接 fixed 
                        fixedDic[fixedT] += $"{__n} = {refStr}{_n}";
                        _callN = __n;
                    }
                    else if (_t != null && isUnsafeDele(_t))// 入参的指针函数 是 不安全（unsafe）
                    {
                        var _deleFunInfo = _unsafeDeleFunDic[_t];
                        var __n = "_" + _n;
                        _callN = __n;
                        var d_args = _deleFunInfo.args;
                        string d_nameStr = "";
                        string d_converStr = "";
                        string deleCallStr = "";
                        //指针函数 的参数列表 遍历 (多层 委托嵌套结构暂不处理)
                        for (int k = 0, len2 = d_args.Count; k < len2; k += 2)
                        {
                            if (k > 1)
                            {
                                d_nameStr += " ,";
                                deleCallStr += " ,";
                            }
                            var d_t = d_args[k];
                            var d_n = d_args[k + 1];
                            d_nameStr += d_n;
                            string d__n = $"_{d_n}";
                            string d_callN = d_n;
                            //char16_t* 的参数
                            if (d_t == C16P)
                            {
                                d_converStr += $"{indentSP} string {d__n} = new string({d_n});{transTool.LF}";
                                d_callN = d__n;
                            }
                            deleCallStr += d_callN;
                        }
                        //处理 委托函数
                        deleFunStr += $"{indentSP}{_t} {__n} = ({d_nameStr})=> {{ {transTool.LF}";
                        indentLevel++;
                        //转string 操作
                        deleFunStr += d_converStr;
                        //safe 委托调用
                        bool hasRet = _deleFunInfo.ret_type != VD;
                        string retStr = hasRet ? RET + " " : "";
                        deleFunStr += $"{indentSP}{retStr}{_n}({deleCallStr});{transTool.LF}";
                        //结尾}
                        indentLevel--;
                        deleFunStr += $"{indentSP}}};{transTool.LF}";
                    }
                    callStr += _callN;
                }
                //fixed 开始
                foreach (var item in fixedDic)
                {
                    _code += $"{indentSP}fixed ({item.Key}* {item.Value}) {{{transTool.LF}";
                    indentLevel++;
                }

                //委托类型 函数定义
                _code += deleFunStr;

                bool retIsVoid = funInfo.ret_type == "void";
                //调用源函数
                string varStr = retIsVoid ? "" : $"var {RKEY} = ";
                _code += $"{indentSP}{varStr}{funInfo.name}({callStr});{transTool.LF}";
                //有 别名Array标记 
                if (retTDecl.isTAliasTagArr)
                {
                    //有别名Array标记 
                    _code += $"{indentSP}var @len = {transTool.RET_ARR_LEN};{transTool.LF}";
                    _code += $"{indentSP}var @arr = new {retTDecl.typeWord}[@len];{transTool.LF}";
                    _code += $"{indentSP}while (@len > 0) {{ @len--; @arr[@len] = __retVal__[@len]; }}{transTool.LF}";
                }

                //return 返回
                if (!retIsVoid)
                {
                    string retStr = RET + " ";
                    string retVal = !retTDecl.isTAliasTagArr ? getSafeFunRetConv(realRetType) : "@arr";
                    _code += $"{indentSP}{retStr}{retVal};{transTool.LF}";
                }

                //fixed 结束
                for (int j = 0, len1 = fixedDic.Count; j < len1; j++)
                {
                    addStrBlockEnd();
                }

                addStrBlockEnd();
                //后半段
                addStrBlockEnd();
                //clear
                fixedDic.Clear();
            }
        }
        /// <summary>
        /// 获取安全方法 的返回 字符串
        /// </summary>
        /// <param name="retType">返回类型 字符串</param>
        /// <returns></returns>
        private string getSafeFunRetConv(string retType)
        {
            switch (retType)
            {
                case STR:
                    return $"new {STR}({RKEY})";
                    break;
                default:
                    return RKEY;
                    break;
            }
        }

        /// <summary>
        /// 获取 函数参数 ，合并后的字符串
        /// </summary>
        /// <param name="funInfo">函数info</param>
        /// <param name="safeMode">是否是安全生成模式</param>
        /// <param name="hasC16P">参数列表中有char16_t*</param>
        /// <returns></returns>
        private string getFunArgsStr(functionInfo funInfo, bool safeMode, ref bool hasC16P)
        {
            bool _hasC16P = hasC16P;
            var resutl = _getArgsStr(funInfo, (_t, _n) =>
            {
                //参数处理
                var _decl = getcsTypeDecl(_t);
                if (_decl.isChar16 && _decl.hasPoint) _hasC16P = true;
                bool needSafe = safeMode || (!isUnsafeDele(_t) && !isRealPointParam(_decl, _n));  //是非安全委托 且 非安全模式，必走typeStr
                var _ctype = needSafe ? typeStrParamSafe(_decl, _n) : typeStr(_decl);
                return _ctype;
            },
            (_t, _n, defVal) =>
            {
                var _decl = getcsTypeDecl(_t);
                var _pns = getPNameSuffix(_n);
                var v = defVal[0];
                var v_T = defVal[1];
                //参数 默认值处理
                string val = v;
                //转换
                if (v_T == "CONSTANT")
                {
                    val = v;
                }
                else
                {
                    bool isRealArr = _decl.arrCount > 0 || _pns == PNameSuffix.ARRAY;

                    //是否是指针 或 数组
                    if (isRealPointParam(_decl, _n) || isRealArr)
                    {
                        val = NL;
                    }
                    else
                    {
                        //给个默认值 ，后期支持 常量定义，再处理常量替换.
                        if (_decl.isEnum)
                        {
                            //是 enum
                            val = $"{_t}.{v}";
                        }
                        else if (_decl.isStruct)
                        {
                            //是 struct 
                            val = $"new {_t}()";
                        }
                        else
                        {
                            //基础类型
                            switch (_t)
                            {
                                case BL: val = FAL; break;
                                default: val = "0"; break;
                            }
                        }
                    }
                }
                if (!string.IsNullOrEmpty(val)) val = $" = {val}";
                return val;
            }
            );

            hasC16P = _hasC16P;

            return resutl;
        }

        /// <summary>
        /// 获取委托 的参数 拼接字符串
        /// </summary>
        /// <param name="funInfo"></param>
        /// <param name="safeMode"></param>
        /// <param name="ignoreC16">忽略char16_t* 转 string</param>
        /// <returns></returns>
        private string getDeleFunArgsStr(functionInfo funInfo, bool safeMode, bool ignoreC16 = false)
        {

            var resutl = _getArgsStr(funInfo, (_t, _n) =>
            {
                var _decl = getcsTypeDecl(_t);
                var needSafe = safeMode || !isRealPointParamDele(_decl, _n);  //除了真指针 ，默认走 safe
                var _ctype = needSafe ? typeStrParamSafe(_decl, _n, ignoreC16) : typeStr(_decl, false, ignoreC16);
                return _ctype;
            });

            return resutl;
        }
        /// <summary>
        /// 获取参数列表 字符串
        /// </summary>
        /// <param name="funInfo">函数info</param>
        /// <param name="pCanvAct">参数转换 处理委托</param>
        /// <returns></returns>
        private string _getArgsStr(functionInfo funInfo, retStringPDel pCanvAct, retStringPDefDel pDefValCanvAct = null)
        {
            var args = funInfo.args;
            string str = "";
            for (int i = 0, len = args.Count; i < len; i += 2)
            {
                var _t = args[i];
                var _name = args[i + 1];
                if (i != 0)
                {
                    str += ",";
                }

                string _ctype = "";
                string _defVal = "";
                if (_t != null)
                {
                    //类型是 voidFun ，替换成 Action
                    if (!_voiddeleFunDic.ContainsKey(_t))
                    {
                        _ctype = pCanvAct.Invoke(_t, _name);
                        if (pDefValCanvAct != null && funInfo.argDefVals.ContainsKey(_name))
                        {
                            _defVal = pDefValCanvAct.Invoke(_t, _name, funInfo.argDefVals[_name]);
                        }
                    }
                    else
                    {
                        _ctype = "Action";
                    }
                }
                else
                {
                    //检查 ... 可变长 参数 params
                    _ctype = "params object[]";
                    _name = "agrs";
                }

                str += $"{_ctype} {_name}{_defVal}";
            }
            return str;
        }

        /// <summary>
        /// 数组类型 转换
        /// </summary>
        /// <param name="c_tStr">c 类型声明</param>
        /// <param name="arrCount">数组的数量</param>
        /// <returns></returns>
        private string arrTypeStrConver(string c_tStr, ref int arrCount)
        {
            if (string.IsNullOrEmpty(c_tStr) || c_tStr[c_tStr.Length - 1] != ']') return c_tStr;
            //确定有 数组
            var regR = Regex.Matches(c_tStr, @"\]");
            arrCount = regR.Count;
            //剔除 数组符号
            int arrIdx = c_tStr.IndexOf("[");
            if (arrIdx == -1) return c_tStr;
            var result = c_tStr.Substring(0, arrIdx);
            return result;
        }

        /// <summary>
        /// 函数 返回值类型字符串转换
        /// </summary>
        /// <param name="_tDecl"></param>
        /// <param name="isOriDecl">是原初的定义</param>
        /// <returns></returns>
        private string typeStrRet(CSTypeDecl _tDecl, bool isOriDecl = false)
        {
            int arrCount = _tDecl.arrCount;
            bool hasPoint = _tDecl.hasPoint;
            string _tWrod = "";//加空格

            if (!_tDecl.isTAliasTagArr)
            {
                _tWrod = tStrConvPoint(_tDecl, false, isOriDecl);
                if (string.IsNullOrEmpty(_tWrod))
                {
                    _tWrod = _tDecl.typeWord;
                }
                else
                {
                    hasPoint = false;
                }
            }
            else
            {
                _tWrod = _tDecl.typeAliasSrcWord;
                if (!isOriDecl)
                {
                    //有效 别名数组
                    hasPoint = false;
                    arrCount++;
                }
            }

            //引用
            string refStr = _tDecl.hasRef ? "ref " : "";
            //指针
            string pStr = hasPoint ? "*" : "";
            //数组
            string arrStr = "";
            for (int i = 0, len = arrCount; i < len; i++)
            {
                arrStr += "[]";
            }

            return $"{refStr}{_tWrod}{pStr}{arrStr}";
        }

        /// <summary>
        /// 函数 参数类型字符串转换
        /// </summary>
        /// <param name="_tDecl">类型声明</param>
        /// <param name="pName">参数名</param>
        /// <param name="ignoreC16">忽略char16_t* 转 string</param>
        /// <returns></returns>
        private string typeStrParamSafe(CSTypeDecl _tDecl, string pName, bool ignoreC16 = false)
        {
            bool hasRef = _tDecl.hasRef;
            int arrCount = _tDecl.arrCount;
            bool isHandle = false;
            string _tWrod = "";
            string _handleName = "";
            if (_tDecl.hasPoint)
            {
                //指针 安全类型 映射
                if (_tDecl.isChar16)
                {
                    _tWrod = STR;
                }
                else if (!_tDecl.isVoidStruct)
                {
                    switch (_tDecl.typeWord)
                    {
                        case VD:
                            isHandle = true;
                            _handleName = VD;
                            break;
                        case C16: _tWrod = STR; break;
                        default:
                            _tWrod = _tDecl.typeWord;
                            var _pNameS = getPNameSuffix(pName);
                            switch (_pNameS)
                            {
                                case PNameSuffix.OUT: hasRef = true; break;
                                case PNameSuffix.ARRAY: arrCount++; break;
                                case PNameSuffix.HANDLE:
                                    isHandle = true;
                                    _handleName = VD;
                                    break;
                            }

                            break;
                    }
                }
                else
                {
                    _handleName = _tDecl.typeWord;
                    isHandle = true;
                }

                if (isHandle)
                {
                    _tWrod = $"{HDL}_{_handleName}";
                }
            }
            else
            {
                _tWrod = _tDecl.typeWord;
                if (isUnsafeDele(_tWrod))
                {
                    //委托,安全的变体壳
                    _tWrod = $"{_tWrod}_{SAF}";
                }
            }
            //引用
            string refStr = hasRef ? "ref " : "";

            //数组
            string arrStr = "";
            for (int i = 0, len = arrCount; i < len; i++)
            {
                arrStr += "[]";
            }

            return $"{refStr}{_tWrod}{arrStr}";
        }
        /// <summary>
        /// 函数 参数或返回值类型 字符串转换
        /// </summary>
        /// <param name="_tDecl">类型声明</param>
        /// <param name="safeMode">安全模式 ，无法识别指针转成 handle_void</param>
        /// <param name="ignoreC16"></param>
        /// <returns></returns>
        private string typeStr(CSTypeDecl _tDecl, bool safeMode = false, bool ignoreC16 = false)
        {
            string _tWrod = "";
            bool hasPoint = _tDecl.hasPoint;
            _tWrod = tStrConvPoint(_tDecl, safeMode, ignoreC16);

            if (string.IsNullOrEmpty(_tWrod))
            {
                _tWrod = _tDecl.typeWord;
            }
            else
            {
                hasPoint = false;   //说明已经 匹配转掉 指针了，不用 加 * 了
            }

            //引用
            string refStr = _tDecl.hasRef ? "ref " : "";
            //指针
            string pStr = hasPoint ? "*" : "";
            //数组
            string arrStr = "";
            for (int i = 0, len = _tDecl.arrCount; i < len; i++)
            {
                arrStr += "[]";
            }
            if (arrStr != "") arrStr = " " + arrStr;    //加空格

            return $"{refStr}{_tWrod}{pStr}{arrStr}";
        }

        /// <summary>
        /// 转换处理 指针类型 ，没有有效匹配 返回一个 "" 字符
        /// </summary>
        /// <param name="_tDecl">声明类型</param>
        /// <param name="safeMode">安全模式，非匹配指针写成句柄</param>
        /// <param name="ignoreC16">忽略char16_t* 转 string</param>
        /// <returns></returns>
        private string tStrConvPoint(CSTypeDecl _tDecl, bool safeMode = false, bool ignoreC16 = false)
        {
            if (!_tDecl.hasPoint) return "";
            //用作 字符串
            if (!ignoreC16 && _tDecl.isChar16)
            {
                return STR;
            }
            else if (_tDecl.isVoidStruct)
            {
                //用作 空结构 handle
                return $"{HDL}_{_tDecl.typeWord}";
            }
            else if (_tDecl.typeWord == VD || safeMode) //safe模式 ，没匹配到的类型指针，强行用作句柄
            {
                //用作 void handle
                return $"{HDL}_{VD}";
            }

            return "";
        }

        /// <summary>
        /// 获取 C# 类型定义
        /// </summary>
        /// <param name="c_tStr">C 类型声明</param>
        /// <returns></returns>
        private CSTypeDecl getcsTypeDecl(string c_tStr)
        {
            if (!_funCsTypeDeclDic.ContainsKey(c_tStr))
            {
                _funCsTypeDeclDic[c_tStr] = parseCTDecl(c_tStr);
            }
            return _funCsTypeDeclDic[c_tStr];
        }

        //解析 一个
        private CSTypeDecl parseCTDecl(string c_tStr)
        {
            //创建 
            CSTypeDecl _td = new CSTypeDecl();
            int arrCount = 0;
            c_tStr = arrTypeStrConver(c_tStr, ref arrCount);
            _td.arrCount = arrCount;
            var _tWord = "";
            var _pI = c_tStr.IndexOf("*");
            if (_pI != -1)
            {
                _td.hasPoint = true;
                _tWord = c_tStr.Substring(0, _pI);
            }

            //是否有引用符
            var _refI = c_tStr.IndexOf("&");
            if (_refI != -1)
            {
                _td.hasRef = true;
                if (_tWord == "")
                {
                    _tWord = c_tStr.Substring(0, _refI);
                }
            }
            if (string.IsNullOrEmpty(_tWord)) _tWord = c_tStr;

            //是个含指针的类型别名
            typeAliasInfo _taSem = null;
            _typeAliasDic.TryGetValue(_tWord, out _taSem);
            //要排除 基础类型同名 的别名 声明
            if (_taSem != null && !CBaseTypeRemap.ContainsKey(_taSem.name))
            {
                string aName = _taSem.name;
                _td.isTAliasTagArr = _taSem.isPoint && aName.Substring(aName.Length - 6) == "_Array";
                if (CBaseTypeRemap.ContainsKey(_taSem.srcType))
                {
                    _td.typeAliasSrcWord = CBaseTypeRemap[_taSem.srcType];
                }
                else
                {
                    _td.typeAliasSrcWord = _taSem.srcType;
                }
                //拆解 别名
                var s_pStr = _taSem.isPoint ? "*" : "";
                var s_arrStr = _taSem.isArr ? "[]" : "";
                //递归获取类型
                var sub_td = parseCTDecl($"{_taSem.srcType}{s_pStr}{s_arrStr}");
                //同步别名状态
                sub_td.isTAliasTagArr = _td.isTAliasTagArr;
                sub_td.typeAliasSrcWord = _td.typeAliasSrcWord;
                return sub_td;  //返回别名
            }

            //是char16
            if (_tWord == C16)
            {
                _td.isChar16 = true;
            }

            //C 的基础类型 映射
            if (CBaseTypeRemap.ContainsKey(_tWord))
            {
                _tWord = CBaseTypeRemap[_tWord];
            }

            //是空结构体类型
            _td.isVoidStruct = _voidStructDic.ContainsKey(_tWord);

            //是结构体
            if (_structDic.ContainsKey(_tWord)) _td.isStruct = true;
            //是枚举
            if (_enumDic.ContainsKey(_tWord)) _td.isEnum = true;

            //类型ID
            _td.typeWord = _tWord;
            return _td;
        }
        /// <summary>
        /// 判断参数声明 是否是真正的 指针
        /// </summary>
        /// <param name="_decl">类型声明</param>
        /// <param name="pName">参数名</param>
        /// <returns></returns>
        private bool isRealPointParam(CSTypeDecl _decl, string pName)
        {
            return _isRealPointP(_decl, pName, false);
        }
        //判断参数声明 是否是真正的 指针(委托)
        private bool isRealPointParamDele(CSTypeDecl _decl, string pName)
        {
            return _isRealPointP(_decl, pName, true);
        }

        //判断参数声明 是否是真正的 指针
        private bool _isRealPointP(CSTypeDecl _decl, string pName, bool isDele)
        {
            if (!_decl.hasPoint) return false;
            if (isDele && _decl.isChar16) return true;
            if (_decl.isTAliasTagArr || _decl.isVoidStruct || _decl.typeWord == VD || (!isDele && _decl.isChar16)) return false;
            if (!string.IsNullOrEmpty(pName))
            {
                var pns = getPNameSuffix(pName);
                if (pns == PNameSuffix.HANDLE) return false;
            }
            return true;
        }

        //判断返回值声明 是否是真正的 指针
        private bool isRealPointRet(CSTypeDecl _decl)
        {
            if (!_decl.hasPoint) return false;
            if (_decl.isTAliasTagArr || _decl.isVoidStruct || _decl.typeWord == VD) return false;
            return true;
        }

        //判断返回值声明 是否是真正的 指针(委托使用)
        private bool isRealPointRetDele(CSTypeDecl _decl)
        {
            if (!_decl.hasPoint) return false;
            if (_decl.isTAliasTagArr || _decl.isVoidStruct || _decl.isChar16 || _decl.typeWord == VD) return false;
            return true;
        }

        /// <summary>
        /// 获取 参名的后缀
        /// </summary>
        /// <param name="pName"></param>
        /// <returns></returns>
        private PNameSuffix getPNameSuffix(string pName)
        {
            if (!_pNameSuffixDic.ContainsKey(pName))
            {
                PNameSuffix result = PNameSuffix.NONE;
                //检查 参数名后缀标识
                var idx = pName.LastIndexOf("_");
                string suffix = "";
                if (idx != -1)
                {
                    suffix = pName.Substring(idx);
                }
                if (suffix != "")
                {
                    switch (suffix)
                    {
                        case "_out": result = PNameSuffix.OUT; break;
                        case "_arr": result = PNameSuffix.ARRAY; break;
                        case "_handle": result = PNameSuffix.HANDLE; break;
                    }
                }
                _pNameSuffixDic[pName] = result;
            }
            return _pNameSuffixDic[pName];
        }
        /// <summary>
        /// 是不安全委托
        /// </summary>
        /// <param name="_t">委托名</param>
        /// <returns></returns>
        private bool isUnsafeDele(string _t)
        {
            return _unsafeDeleFunDic.ContainsKey(_t);
        }

        //是否函数不安全  不安全
        private bool isFunUnsafe(functionInfo funInfo)
        {
            var ret_decl = getcsTypeDecl(funInfo.ret_type);
            //if (ret_decl.hasPoint || ret_decl.isTAliasTagArr)
            if (isRealPointRet(ret_decl))
            {
                return true;
            }

            for (int i = 0, len = funInfo.args.Count; i < len; i += 2)
            {
                string _t = funInfo.args[i];
                string _n = funInfo.args[i + 1];
                if (_t == null) continue;
                var _decl = getcsTypeDecl(_t);
                if (isRealPointParam(_decl, _n) || isUnsafeDele(_t)) return true;
            }
            return false;
        }

        //是否委托不安全 不安全(委托)
        private bool isDeleFunUnsafe(functionInfo funInfo)
        {
            var ret_decl = getcsTypeDecl(funInfo.ret_type);
            if (isRealPointRetDele(ret_decl)) return true;

            for (int i = 0, len = funInfo.args.Count; i < len; i += 2)
            {
                string _t = funInfo.args[i];
                string _n = funInfo.args[i + 1];
                if (_t == null) continue;
                var _decl = getcsTypeDecl(_t);
                if (isRealPointParamDele(_decl, _n) || isUnsafeDele(_t)) return true;
            }
            return false;
        }
        //获取全名 （枚举）
        private string getFillName(enumInfo info)
        {
            return transTool.getFillScopeN(info.scopeArr) + info.name;
        }
        //获取全名（结构）
        private string getFillName(structInfo info)
        {
            return transTool.getFillScopeN(info.scopeArr) + info.name;
        }
    }
}
